package graphics;

import static org.lwjgl.opengl.GL11.*;

import graphics.handlers.GLFPSHandler;
import graphics.handlers.GLTextFormatHandler;
import graphics.object.testing.GLArrowMovementRect;
import graphics.object.testing.GLMouseInfoTextRect;
import graphics.object.testing.GLTestingRectangle;
import graphics.object.testing.GLWritableTextRectangle;

import java.awt.Color;
import java.awt.FontFormatException;
import java.io.File;
import java.io.IOException;
import org.lwjgl.LWJGLException;
import org.lwjgl.Sys;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.UnicodeFont;
import org.newdawn.slick.font.effects.ColorEffect;

public class TestingGraphics {
    //fa3Aw2Qn5Gr9

    public static int width = 750;
    public static int height = 700;
    public static float translate_x = 0;
    public static float translate_y = 0;
    public static int maxFPS = 70;

    public static UnicodeFont font;

    //Managers
    public static GLEventManager eventManager;
    public static GLObjectManager objectManager;
    //

    public static void main(String[] args){
        new TestingGraphics();
    }

    public TestingGraphics(){
        try {
            Display.setDisplayMode(new DisplayMode(width, height));
            Display.setTitle("Test FPS: Init");
            Display.create();
        } catch (LWJGLException e) {
            e.printStackTrace();
            System.exit(0);
        }

        initGL();
        initFont();

        //Start managers
        eventManager = new GLEventManager();
        objectManager = new GLObjectManager();
        //
        //Start Handlers
        objectManager.addObject(new GLTextFormatHandler());
        objectManager.addObject(new GLFPSHandler());
        //
        //Add Renderable stuff.
        objectManager.addObject(new GLTestingRectangle(new Color(255, 100, 100), -200,0,50,height + 50));
        objectManager.addObject(new GLTestingRectangle(new Color(255, 100, 100), -100,0,50,height + 50));
        objectManager.addObject(new GLTestingRectangle(new Color(255, 100, 100), 0,0,50,height + 50));
        objectManager.addObject(new GLTestingRectangle(new Color(255, 100, 100), 100,0,50,height + 50));
        objectManager.addObject(new GLTestingRectangle(new Color(255, 100, 100), 200,0,50,height + 50));
        objectManager.addObject(new GLTestingRectangle(new Color(255, 100, 100), 300,0,50,height + 50));

        objectManager.addObject(new GLTestingRectangle(new Color(255, 100, 100), -200,0,550,50));
        objectManager.addObject(new GLTestingRectangle(new Color(255, 100, 100), -200,100,550,50));
        objectManager.addObject(new GLTestingRectangle(new Color(255, 100, 100), -200,200,550,50));
        objectManager.addObject(new GLTestingRectangle(new Color(255, 100, 100), -200,300,550,50));
        objectManager.addObject(new GLTestingRectangle(new Color(255, 100, 100), -200,400,550,50));
        objectManager.addObject(new GLTestingRectangle(new Color(255, 100, 100), -200,500,550,50));
        objectManager.addObject(new GLTestingRectangle(new Color(255, 100, 100), -200,600,550,50));
        objectManager.addObject(new GLTestingRectangle(new Color(255, 100, 100), -200,700,550,50));
        
        objectManager.addObject(new GLArrowMovementRect(new Color(100, 255, 100), -200,700,50,50));
        
        objectManager.addObject(new GLMouseInfoTextRect(500, 200));
        objectManager.addObject(new GLWritableTextRectangle("ABCDEFGHIJKLMNOPQRSTUVWXYZ\nabcdefghijklmnopqrstuvwxyz\n1234567890\n!@#$%^&*()\n", 500, 400));
        //

        loop();
    }

    @SuppressWarnings("unchecked")
    public void initFont(){
        java.awt.Font awtFont;
        try {
            awtFont = java.awt.Font.createFont(java.awt.Font.TRUETYPE_FONT , new File("resources/kroe0655.ttf"));
            awtFont = awtFont.deriveFont(15f);
            //java.awt.Font awtFont = new java.awt.Font("Times New Roman", java.awt.Font.BOLD, 18);
            font = new UnicodeFont(awtFont);
            font.getEffects().add(new ColorEffect(java.awt.Color.white));
            font.addAsciiGlyphs();
            font.loadGlyphs();
        } catch (FontFormatException e1) {
            e1.printStackTrace();
        } catch (IOException e1) {
            e1.printStackTrace();
        } catch (SlickException e) {
            e.printStackTrace();
            Display.destroy();
            System.exit(0);
        }
    }

    public void initGL(){
        glEnable(GL_TEXTURE_2D);
        glShadeModel(GL_SMOOTH);       
        glDisable(GL_DEPTH_TEST);
        glDisable(GL_LIGHTING);                   

        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);               
        glClearDepth(1);                                      

        glEnable(GL_BLEND);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glViewport(0,0,width,height);
        glMatrixMode(GL_MODELVIEW);

        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrtho(0, width, height, 0, 1, -1);
        glMatrixMode(GL_MODELVIEW);
    }

    public void loop(){
        long lastTickTime = 0;
        long deltaTime = 0;
        float mouseDeltaX = 0f;
        float mouseDeltaY = 0f;
        while (!Display.isCloseRequested()) {
            deltaTime = getTime() - lastTickTime;
            lastTickTime = getTime();
            eventManager.eventTick(getTime(), deltaTime);
            while(Mouse.next()){
                if(Mouse.getEventButtonState()){
                    eventManager.eventMousePress(Mouse.getEventButton(), getMouseRealX(), getMouseRealY());
                }else{
                    eventManager.eventMouseRelease(Mouse.getEventButton(), getMouseRealX(), getMouseRealY());
                }
            }
            while (Keyboard.next()) {
                if(Keyboard.getEventKeyState()){
                    eventManager.eventKeyPressed(Keyboard.getEventKey());
                }else{
                    eventManager.eventKeyReleased(Keyboard.getEventKey());
                }
            }
            //You can only get the Delta Once, so I stored it.
            mouseDeltaX = Mouse.getDX();
            mouseDeltaY = Mouse.getDY();
            //
            if(mouseDeltaX != 0 || mouseDeltaY != 0){
                eventManager.eventMouseMove(getMouseRealX(), getMouseRealY(), (int)mouseDeltaX, (int)mouseDeltaY);
            }

            eventManager.eventRender();
            Display.update();
            Display.sync(maxFPS);
        }
        Display.destroy();
        System.exit(0);
    }

    public static int getMouseRealX(){
        return (int) (Mouse.getX() - translate_x);
    }

    public static int getMouseRealY(){
        return (int)((height - Mouse.getY() - 1) - translate_y);
    }

    public static long getTime(){
        return (Sys.getTime() * 1000) / Sys.getTimerResolution();
    }
}
